home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
mint
/
editors
/
mjovesrc.zoo
/
re1.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-04
|
13KB
|
607 lines
/***************************************************************************
* This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE *
* is provided to you without charge, and with no warranty. You may give *
* away copies of JOVE, including sources, provided that this notice is *
* included in all the files. *
***************************************************************************/
#include "jove.h"
#include "fp.h"
#include "re.h"
#include "ctype.h"
#include "chars.h"
#include "disp.h"
#ifdef MAC
# include "mac.h"
#else
# include <sys/stat.h>
#endif
private void
IncSearch proto((int));
private int
isearch proto((int, Bufpos *));
private int
substitute(re_blk, query, l1, char1, l2, char2)
struct RE_block *re_blk;
Line *l1,
*l2;
bool query;
int char1,
char2;
{
Line *lp;
int numdone = 0,
UNDO_nd = 0,
offset = char1;
bool stop = NO;
daddr UNDO_da = NULL_DADDR;
Line *UNDO_lp = NULL;
lsave();
for (lp = l1; lp != l2->l_next; lp = lp->l_next) {
int crater = -1; /* end of last substitution on this line */
int LineDone = NO; /* already replaced last empty string on line? */
while (!LineDone
&& re_lindex(lp, offset, FORWARD, re_blk, NO, crater)
&& (lp != l2 || REeom <= char2))
{
DotTo(lp, REeom);
offset = curchar;
if (query) {
int c;
message("Replace (Type '?' for help)? ");
reswitch:
redisplay();
c = jgetchar();
if (c == AbortChar)
return numdone;
switch (CharUpcase(c)) {
case '.':
stop = YES;
/*FALLTHROUGH*/
case ' ':
case 'Y':
break;
case BS:
case RUBOUT:
case 'N':
if (REbom == REeom) {
offset += 1;
if (linebuf[REeom] == '\0')
LineDone = YES;
}
continue;
case CTL('W'):
re_dosub(re_blk, linebuf, YES);
if (lp == l2)
char2 += REdelta;
modify();
numdone += 1;
curchar = REbom;
makedirty(curline);
UNDO_da = curline->l_dline;
UNDO_lp = curline;
/*FALLTHROUGH*/
case CTL('R'):
case 'R':
RErecur();
UNDO_lp = NULL; /* can't reliably undo this */
offset = curchar;
lp = curline;
continue;
case CTL('U'):
case 'U':
if (UNDO_lp == NULL) {
rbell();
goto reswitch;
}
if (UNDO_lp == NULL)
getline(UNDO_da, linebuf); /* someone ought to */
lp = UNDO_lp;
lp->l_dline = UNDO_da;
makedirty(lp);
offset = 0;
numdone = UNDO_nd;
UNDO_lp = NULL;
continue;
case 'P':
case '!':
query = FALSE;
break;
case CR:
case LF:
case 'Q':
return numdone;
case CTL('L'):
RedrawDisplay();
goto reswitch;
default:
rbell();
message("Space or Y, Period, Rubout or N, C-R or R, C-W, C-U or U, P or !, Return.");
goto reswitch;
}
}
if (UNDO_lp != curline) {
UNDO_da = curline->l_dline;
UNDO_lp = curline;
UNDO_nd = numdone;
}
if (REbom == REeom && linebuf[REeom] == '\0')
LineDone = YES;
re_dosub(re_blk, linebuf, NO);
if (lp == l2)
char2 += REdelta;
numdone += 1;
modify();
crater = offset = curchar = REeom;
makedirty(curline);
if (query) {
message(mesgbuf); /* no blinking */
redisplay(); /* show the change */
}
if (stop)
return numdone;
}
offset = 0;
}
return numdone;
}
/* prompt for search and replacement strings and do the substitution */
private void
replace(query, inreg)
bool query,
inreg;
{
Mark *m;
char *rep_ptr;
Line *l1 = curline,
*l2 = curbuf->b_last;
int char1 = curchar,
char2 = length(curbuf->b_last),
numdone;
struct RE_block re_blk;
if (inreg) {
m = CurMark();
l2 = m->m_line;
char2 = m->m_char;
(void) fixorder(&l1, &char1, &l2, &char2);
}
/* get search string */
strcpy(rep_search, ask(rep_search[0] ? rep_search : (char *)NULL, ProcFmt));
REcompile(rep_search, UseRE, &re_blk);
/* Now the replacement string. Do_ask() so the user can play with
the default (previous) replacement string by typing C-R in ask(),
OR, he can just hit Return to replace with nothing. */
rep_ptr = do_ask("\r\n", (bool (*) ptrproto((int))) NULL, rep_str,
": %f %s with ", rep_search);
if (rep_ptr == NULL)
rep_ptr = NullStr;
strcpy(rep_str, rep_ptr);
if ((numdone = substitute(&re_blk, query, l1, char1, l2, char2)) != 0
&& !inreg)
{
do_set_mark(l1, char1);
add_mess(" "); /* just making things pretty */
} else {
message("");
}
add_mess("(%d substitution%n)", numdone, numdone);
}
void
RegReplace()
{
replace(NO, YES);
}
void
QRepSearch()
{
replace(YES, NO);
}
void
RepSearch()
{
replace(NO, NO);
}
/* Lookup a tag in tag file FILE. FILE is assumed to be sorted
alphabetically. The FASTTAGS code, which is implemented with
a binary search, depends on this assumption. If it's not true
it is possible to comment out the fast tag code (which is clearly
labeled), delete the marked test in the sequential loop, and
everything else will just work. */
private bool
lookup(searchbuf, filebuf, tag, file)
char *searchbuf,
*filebuf,
*tag,
*file;
{
register size_t taglen = strlen(tag);
char line[JBUFSIZ],
pattern[128];
register File *fp;
struct stat stbuf;
bool success = NO;
fp = open_file(file, iobuff, F_READ, NO, YES);
if (fp == NULL)
return NO;
swritef(pattern, sizeof(pattern), "^%s[^\t]*\t*\\([^\t]*\\)\t*\\([?/]\\)\\(.*\\)\\2$", tag);
/* ********BEGIN FAST TAG CODE******** */
if (stat(file, &stbuf) >= 0) {
/* Invariant: if there is a line matching the tag, it
* begins somewhere after position lower, and begins
* at or before upper. There is one possible
* exception: if lower is 0, the line with the tag
* might be the very first line.
*
* When this loop is done, we seek to lower, advance
* past the next newline (unless lower is 0), and fall
* into the sequential search.
*/
register off_t lower = 0;
register off_t upper = stbuf.st_size;
for (;;) {
off_t mid;
int chars_eq;
if (upper - lower < JBUFSIZ)
break; /* small range: search sequentially */
mid = (lower + upper) / 2;
f_seek(fp, mid); /* mid will not be 0 */
f_toNL(fp);
if (f_gets(fp, line, sizeof line))
break; /* unexpected: bail out */
chars_eq = numcomp(line, tag);
if (chars_eq == taglen && jiswhite(line[chars_eq])) {
/* we hit the exact line: get out */
lower = mid;
break;
}
if (line[chars_eq] < tag[chars_eq])
lower = mid; /* line is BEFORE tag */
else
upper = mid; /* line is AFTER tag */
}
/* sequentially search from lower */
f_seek(fp, lower);
if (lower > 0)
f_toNL(fp);
}
/* END FAST TAG CODE */
while (!f_gets(fp, line, sizeof line)) {
int cmp = line[0] - *tag;
if (cmp == 0) {
cmp = strncmp(line, tag, taglen);
if (cmp == 0) {
/* we've found the match */
if (!LookingAt(pattern, line, 0)) {
complain("I thought I saw it!");
} else {
putmatch(1, filebuf, (size_t)FILESIZE);
putmatch(3, searchbuf, (size_t)100);
success = YES;
}
break;
}
}
if (cmp > 0)
break; /* failure: gone too far. PRESUMES ALPHABETIC ORDER */
}
close_file(fp);
if (success == NO)
s_mess("Can't find tag \"%s\".", tag);
return success;
}
char TagFile[FILESIZE] = "tags";
void
find_tag(tag, localp)
char *tag;
int localp;
{
char filebuf[FILESIZE],
sstr[100],
tfbuf[FILESIZE];
register Bufpos *bp;
register Buffer *b;
char *tagfname;
if (!localp) {
char prompt[128];
swritef(prompt, sizeof(prompt), "With tag file (%s default): ", TagFile);
tagfname = ask_file(prompt, TagFile, tfbuf);
} else
tagfname = TagFile;
if (!lookup(sstr, filebuf, tag, tagfname))
return;
set_mark();
b = do_find(curwind, filebuf, NO);
if (curbuf != b)
SetABuf(curbuf);
SetBuf(b);
if ((bp = dosearch(sstr, BACKWARD, NO)) == NULL &&
((bp = dosearch(sstr, FORWARD, NO)) == NULL))
message("Well, I found the file, but the tag is missing.");
else
SetDot(bp);
}
void
FindTag()
{
int localp = !is_an_arg();
char tag[128];
strcpy(tag, ask((char *)NULL, ProcFmt));
find_tag(tag, localp);
}
/* Find Tag at Dot